package cn.apestar.modules.report.useraccount.util;

import static jodd.datetime.JDateTimeDefault.format;

import java.lang.reflect.InvocationTargetException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.beanutils.BeanUtils;

/**
 * 该类是将传入的对象列表List，通过两个字段名对其进行分类 作用：便于通过两个字段值查询列表中对象的具体数据 Created by Singer_YDW on 2016/9/21.
 */
public class UserAccountUtil {

    /**
     * 内部总列表
     */
    private static List localList = null;

    /**
     * 根据字段名分类列表
     */
    private static Map<String, Map<String, Object>> listForCol = null;

    /**
     * 内部日期
     */
    private static Date localDate = null;

    /**
     * 内部日期列表（Date）
     */
    private static List<Date> locallistDate = null;

    /**
     * 内部日期列表（String）
     */
    private static List<String> locallistString = null;

    /**
     * 根据列名初始化要处理的列表
     * @param dataList 要处理的列表
     * @param colName1 字段名1
     * @param colName2 字段名2
     */
    public static void initDataList(List<?> dataList, String colName1, String colName2, boolean hasDate) {
        if (localList == null && dataList != null) {
            localList = dataList;
            sortListByDateAndCol(colName1, colName2, hasDate);
        } else if (localList.hashCode() != dataList.hashCode() && dataList != null) {
            localList = dataList;
            listForCol = null;
            sortListByDateAndCol(colName1, colName2, hasDate);
        }
    }

    /**
     * 根据字段值colValue1和colValue2获取对应数据
     * @param colValue1 字段值1
     * @param colValue2 字段值2
     * @return (返回要查询的Object对象)
     */
    public static Object getObjFromColName(String colValue1, String colValue2) {

        Object result = null;

        if (listForCol != null) {
            Map<String, Object> map = listForCol.get(colValue1);
            if (map != null)
                return map.get(colValue2);
        }

        return result;
    }

    /**
     * 归类列表数据到Map中
     * @param colName1 字段1
     * @param colName2 字段2
     */
    private static void sortListByDateAndCol(Object colName1, Object colName2, boolean hasDate) {
        if (localList != null) {
            listForCol = new HashMap<>();
            for (Object obj : localList) {
                putMapDataForReflect(obj, colName1, colName2, hasDate);
            }
        }
    }

    /**
     * 通过给予的字段名，获取对应数据存放到Col2的Map列表中
     * @param obj 对象
     * @param colName1 第一列列名
     * @param colName2 第二列列名
     * @return
     */
    private static void putMapDataForReflect(Object obj, Object colName1, Object colName2, boolean hasDate) {
        Map<String, Object> resultMap = null;
        String col1Data = null;
        String col2Data = null;
        try {
            col1Data = BeanUtils.getProperty(obj, colName1.toString());
            col2Data = BeanUtils.getProperty(obj, colName2.toString());
            if (hasDate) {
                try {
                    Date date = new Date(col2Data);
                    col2Data = new SimpleDateFormat("yyyy-MM-dd").format(date);
                } catch (Exception e) {
                    Date date = new Date(col1Data);
                    col1Data = new SimpleDateFormat("yyyy-MM-dd").format(date);
                }
            }
            // 将值放到map列表中
            putCol2MapList(obj, col1Data, col2Data);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
    }

    /**
     * 添加Map中的ColName2的Map列表
     * @param obj 数据对象
     * @param col1Data 第一列数据
     * @param col2Data 第二列数据
     */
    private static void putCol2MapList(Object obj, String col1Data, String col2Data) {
        Map<String, Object> colName2ObjectMap = null;
        if (listForCol.containsKey(col1Data))
            colName2ObjectMap = listForCol.get(col1Data);
        else {
            colName2ObjectMap = new HashMap<>();
        }
        colName2ObjectMap.put(col2Data, obj);
        listForCol.put(col1Data, colName2ObjectMap);
    }

    /**
     * Map对象数据转换为List对象 //TODO 添加方法功能描述
     */
    public static List<?> colMapBackToList() {

        Collections.sort(localList);
        return localList;
    }

    /**
     * 获取内部map对象大小
     * @return 大小
     */
    public static int getInnerMapSize() {
        return listForCol.size();
    }

    /**
     * 获取日期date的x天以前的天数
     * @param startDate 开始时间
     * @param endDate 结束时间
     * @param format 要返回时间的格式
     * @param x 多少天
     * @return
     */
    public static List<?> getBeforeXDayListByString(Date startDate, Date endDate, String format, int x) {
        if (localDate != null)
            localDate = endDate;
        else if (localDate.hashCode() != endDate.hashCode())
            localDate = endDate;
        String setDateS = new SimpleDateFormat("yyyy-MM-dd").format(localDate);

        Date nowDate = new Date();
        String nowDateS = new SimpleDateFormat("yyyy-MM-dd").format(nowDate);
        String startDateS = new SimpleDateFormat("yyyy-MM-dd").format(startDate);
        if (setDateS.compareTo(nowDateS) >= 0)
            endDate = nowDate;

        try {
            int disX = daysBetween(startDateS, nowDateS);
            if ((disX - 1) < 10)
                x = disX + 1;
        } catch (ParseException e) {
            e.printStackTrace();
        }
        locallistString = new ArrayList<>();
        SimpleDateFormat df = new SimpleDateFormat(format);
        for (int i = 0; i < x; i++) {
            locallistString.add(df.format(new Date(endDate.getTime() - i * 24 * 60 * 60 * 1000)));
        }
        return locallistString;
    }

    /**
     * 获取日期date的x天以前的天数
     * @param startDate 开始时间
     * @param endDate 结束时间
     * @param x 多少天
     * @return
     */
    public static List<?> getBeforeXDayListByDate(Date startDate, Date endDate, int x) {
        if (localDate != null)
            localDate = endDate;
        else if (localDate.hashCode() != endDate.hashCode())
            localDate = endDate;
        String setDateS = new SimpleDateFormat("yyyy-MM-dd").format(localDate);

        Date nowDate = new Date();
        String nowDateS = new SimpleDateFormat("yyyy-MM-dd").format(nowDate);
        String startDateS = new SimpleDateFormat("yyyy-MM-dd").format(startDate);
        if (setDateS.compareTo(nowDateS) >= 0)
            endDate = nowDate;

        try {
            int disX = daysBetween(startDateS, nowDateS);
            if ((disX - 1) < 10)
                x = disX + 1;
        } catch (ParseException e) {
            e.printStackTrace();
        }
        locallistDate = new ArrayList<>();
        for (int i = 0; i < x; i++) {
            locallistDate.add(new Date(endDate.getTime() - i * 24 * 60 * 60 * 1000));
        }
        return locallistDate;
    }

    /**
     * 获取日期date的x天以前的天数
     * @param date 时间
     * @param x 多少天
     * @return 所有天数Date列表
     */
    public static List<?> getBeforeXDayListByDate(Date date, int x) {
        if (localDate != null)
            localDate = date;
        else if (localDate.hashCode() != date.hashCode())
            localDate = date;
        locallistDate = new ArrayList<>();
        for (int i = 0; i < x; i++) {
            locallistDate.add(new Date(date.getTime() - i * 24 * 60 * 60 * 1000));
        }
        return locallistDate;
    }

    /**
     * 获取日期date的x天以前的天数
     * @param startDate 开始时间
     * @param endDate 结束
     * @return 所有天数Date列表
     */
    public static List<?> getBeforeDayListByDate(Date startDate, Date endDate) {
        int x = 10;
        try {
            x = daysBetween(startDate, endDate);
            x = x > 10 ? 10 : x;
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (localDate != null)
            localDate = startDate;
        else if (localDate.hashCode() != startDate.hashCode())
            localDate = startDate;
        else
            return locallistDate;
        locallistDate = new ArrayList<>();
        for (int i = 0; i < x; i++) {
            locallistDate.add(new Date(startDate.getTime() - i * 24 * 60 * 60 * 1000));
        }
        return locallistDate;
    }

    /**
     * 获取日期date的x天以前的天数
     * @param startDate 开始时间
     * @param x 多少天
     * @return 所有天数Date列表
     */
    public static List<?> getAfterXDayListByDate(Date startDate, int x) {
        if (localDate != null) {
            String setDateS = new SimpleDateFormat("yyyy-MM-dd").format(localDate);

            Date nowDate = getNowDate();
            String nowDateS = new SimpleDateFormat("yyyy-MM-dd").format(nowDate);
            String startDateS = new SimpleDateFormat("yyyy-MM-dd").format(startDate);
            if (setDateS.compareTo(nowDateS) >= 0)
                localDate = nowDate;

            try {
                int disX = daysBetween(startDateS, nowDateS);
                if ((disX - 1) < 10)
                    x = disX + 1;
                if (x <= 0) {
                    startDate = nowDate;
                    return getBeforeXDayListByDate(10);
                }
            } catch (ParseException e) {
                e.printStackTrace();
            }
            locallistDate = new ArrayList<>();
            for (int i = 0; i < x; i++) {
                locallistDate.add(new Date(startDate.getTime() + i * 24 * 60 * 60 * 1000));
            }
            Collections.reverse(locallistDate);
            return locallistDate;
        }
        return locallistDate;
    }

    /**
     * 获取日期date的x天以前的天数
     * @return 所有天数Date列表
     */
    public static List<?> getBeforeXDayListByDate(int x) {
        if (localDate != null) {
            locallistDate = new ArrayList<>();
            for (int i = 0; i < x; i++) {
                locallistDate.add(new Date(localDate.getTime() - i * 24 * 60 * 60 * 1000));
            }
            return locallistDate;
        }
        Collections.reverse(locallistDate);
        return locallistDate;
    }

    /**
     * 获取日期date的x天以前的天数
     * @param endDate 结束时间
     * @return
     */
    public static List<?> getBeforeDayListByDate(Date endDate) {
        int x = 10;
        try {
            x = daysBetween(localDate, endDate);
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (localDate != null) {
            locallistDate = new ArrayList<>();
            for (int i = 0; i < x; i++) {
                locallistDate.add(new Date(localDate.getTime() - i * 24 * 60 * 60 * 1000));
            }
            Collections.sort(locallistDate);
        }
        return locallistDate;
    }

    /**
     * 获取日期date的x天以前的天数
     * @param startDate 开始时间
     * @return
     */
    public static List<?> getAfterDayListByDate(Date startDate) {
        int x = 10;
        try {
            x = daysBetween(startDate, localDate);
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (localDate != null) {
            locallistDate = new ArrayList<>();
            for (int i = 0; i < x; i++) {
                locallistDate.add(new Date(localDate.getTime() + i * 24 * 60 * 60 * 1000));
            }
            Collections.sort(locallistDate);
        }
        return locallistDate;
    }

    /**
     * 获取两个时间之间的所有时间列表
     * @param startDate 开始时间
     * @param endDate 结束时间
     * @return 时间列表
     */
    public static List<?> getOffsetDateList(Date startDate, Date endDate) {
        int count = 0;
        try {
            if (compareDate(endDate, getNowDate()) > 0)
                endDate = getNowDate();
            if (compareDate(startDate, getNowDate()) > 0)
                startDate = getNowDate();
            count = daysBetween(startDate, endDate) + 1;
            count = count > 25 ? 25 : count;
            setRecordCount(count);
        } catch (ParseException e) {
            count = 10;
        }
        if (localDate != null) {
            locallistDate = new ArrayList<>();
            for (int i = 0; i < count; i++) {
                locallistDate.add(new Date(startDate.getTime() + i * 24 * 60 * 60 * 1000));
            }
            Collections.reverse(locallistDate);
        }
        return locallistDate;
    }

    /**
     * 获取日期date的x天以后的天数
     * @return 所有天数Date列表
     */
    public static List<?> getAfterXDayListByDate(int x) {
        if (localDate != null) {
            locallistDate = new ArrayList<>();
            for (int i = 0; i < x; i++) {
                locallistDate.add(new Date(localDate.getTime() + i * 24 * 60 * 60 * 1000));
            }
        }
        return locallistDate;
    }

    /**
     * 获取日期date的x天以前的天数
     * @return 所有天数Date列表
     */
    public static List<?> getBeforeXDayListByString(int x) {
        if (localDate != null) {
            locallistString = new ArrayList<>();
            SimpleDateFormat df = new SimpleDateFormat(format);
            for (int i = 0; i < x; i++) {
                locallistString.add(df.format(new Date(localDate.getTime() - i * 24 * 60 * 60 * 1000)));
            }
        }
        return locallistString;
    }

    /**
     * 设置内部时间
     * @param date
     */

    public static void setLocalDate(Date date) {
        localDate = date;
    }

    /**
     * 计算两个日期之间相差的天数
     * @param smdate 较小的时间
     * @param bdate 较大的时间
     * @return 相差天数
     * @throws ParseException
     */
    public static int daysBetween(Date smdate, Date bdate) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        smdate = sdf.parse(sdf.format(smdate));
        bdate = sdf.parse(sdf.format(bdate));
        Calendar cal = Calendar.getInstance();
        cal.setTime(smdate);
        long time1 = cal.getTimeInMillis();
        cal.setTime(bdate);
        long time2 = cal.getTimeInMillis();
        long between_days = (time2 - time1) / (1000 * 3600 * 24);

        return Integer.parseInt(String.valueOf(between_days));
    }

    /**
     * 字符串的日期格式的计算
     */
    public static int daysBetween(String smdate, String bdate) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Calendar cal = Calendar.getInstance();
        cal.setTime(sdf.parse(smdate));
        long time1 = cal.getTimeInMillis();
        cal.setTime(sdf.parse(bdate));
        long time2 = cal.getTimeInMillis();
        long between_days = (time2 - time1) / (1000 * 3600 * 24);

        return Integer.parseInt(String.valueOf(between_days));
    }

    /**
     * 获取较大日期
     * @param date01 日期1
     * @param date02 日期2
     * @return 较大日期
     */
    public static Date getMaxDate(Date date01, Date date02) {
        if (date01 != null && date02 != null) {
            Calendar cal = Calendar.getInstance();
            cal.setTime(date01);
            long time1 = cal.getTimeInMillis();
            cal.setTime(date02);
            long time2 = cal.getTimeInMillis();
            return time1 > time2 ? date01 : date02;
        }
        if (date01 != null)
            return date01;
        if (date02 != null)
            return date02;

        return new Date();
    }

    /**
     * 获取较小日期
     * @param date01 日期1
     * @param date02 日期2
     * @return 较大日期
     */
    public static Date getMinDate(Date date01, Date date02) {
        if (date01 != null && date02 != null) {
            Calendar cal = Calendar.getInstance();
            cal.setTime(date01);
            long time1 = cal.getTimeInMillis();
            cal.setTime(date02);
            long time2 = cal.getTimeInMillis();
            return time1 > time2 ? date02 : date01;
        }
        if (date01 != null)
            return date01;
        if (date02 != null)
            return date02;

        return new Date();
    }

    /**
     * 比较练歌日期大小
     * @param date01 日期1
     * @param date02 日期2
     * @return 1, 0,-1
     */
    public static int compareDate(Date date01, Date date02) {
        if (date01 != null && date02 != null) {
            SimpleDateFormat dformat = new SimpleDateFormat("yyyy-MM-dd");
            String dateS01 = dformat.format(date01);
            String dateS02 = dformat.format(date02);
            return dateS01.compareTo(dateS02);
        }
        return -1;
    }

    private static Date nowDate;

    public static void setNowDate(Date date) {
        nowDate = date;
    }

    public static Date getNowDate() {
        return nowDate;
    }

    private static int recordCount;

    public static void setRecordCount(int count) {
        recordCount = count;
    }

    public static int getRecordCount() {
        return recordCount;
    }
}
